/*
	This profiler is from Richard Fine's article on gamedev.net titled "Enginuity",
	all of this amazing code is credited to him.
*/


#ifndef PROFILER_H
#define PROFILER_H

#include "SDL.h" // used for time
#include <string>
using namespace std;

const int MAX_PROFILER_SAMPLES = 50;

class ProfilerOutputHandler;
class ProfileSample;

class ProfileSample
{
public:
	ProfileSample(string sampleName);
	~ProfileSample();

	static void Output();
	static void ResetSample(string sampleName);
	static void ResetAll();
	static ProfilerOutputHandler *outputHandler;
	static bool bProfilerIsRunning;

protected:
	int iSampleIndex;
	int iParentIndex;

	inline float GetTime() { return ((float)SDL_GetTicks())/1000.0f; }

	static struct profileSample {
		profileSample()
		{
			bIsValid = false;
			dataCount = 0;
			averagePc = minPc = maxPc = -1;
		}

		bool bIsValid;
		bool bIsOpen;
		unsigned int callCount;
		string name;
		float startTime;
		float totalTime;
		float childTime;
		int parentCount;
		float averagePc;
		float minPc;
		float maxPc;
		unsigned long dataCount;
	} samples[MAX_PROFILER_SAMPLES];
	static int lastOpenedSample;
	static int openSampleCount;
	static float rootBegin, rootEnd;
};

class ProfilerOutputHandler
{
public:
	virtual void BeginOutput(float tTotal)=0;
	virtual void Sample(float fMin, float fAvg, float fMax, float tAvg, int callCount, string name, int parentCount)=0;
	virtual void EndOutput()=0;
};

#ifdef PROFILER
#define PROFILE(name) ProfileSample _profile_sample(name);
#else
#define PROFILE(name)
#endif

#endif